/// This module contains string hash functions based on the djb2 algorithm.
/// The functions compute a hash value for a given string, with an option to
/// ignore case sensitivity.
pub mod hash_string {
    /// Computes the djb2 hash for a given string.
    ///
    /// # Arguments
    ///
    /// * `string` - A string slice to compute the hash for.
    ///
    /// # Returns
    ///
    /// The computed hash value as an `u32`.
    pub fn string_hash(string: &str) -> u32 {
        let mut result: u32 = 5381;

        for &c in string.as_bytes() {
            result = (result << 5).wrapping_add(result).wrapping_add(c as u32);
        }

        result
    }

    /// Computes the djb2 hash for a given string, ignoring case sensitivity.
    ///
    /// # Arguments
    ///
    /// * `string` - A string slice to compute the hash for.
    ///
    /// # Returns
    ///
    /// The computed hash value as an `u32`.
    pub fn string_nocase_hash(string: &str) -> u32 {
        let mut result: u32 = 5381;

        for &c in string.as_bytes() {
            let lower_char = c.to_ascii_lowercase();
            result = (result << 5).wrapping_add(result).wrapping_add(lower_char as u32);
        }

        result
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn test_string_hash() {
            let test_string = "hello";
            let hash_value: u32 = string_hash(test_string);
            assert_eq!(hash_value, 0x79f6e004);
        }

        #[test]
        fn test_string_nocase_hash() {
            let test_string = "Hello";
            let hash_value: u32 = string_nocase_hash(test_string);
            assert_eq!(hash_value, 0x79f6e004);
        }

        #[test]
        fn test_string_nocase_hash_mixed_case() {
            let test_string = "HeLLo";
            let hash_value: u32 = string_nocase_hash(test_string);
            assert_eq!(hash_value, 0x79f6e004);
        }
    }
}
